@ Title: Numeros primos     	                   Filename: Primes.s
@ Author: Rodolfo Alfredo Quezada Nevarez          Date: 16 / Marzo / 2016
@ Description: Busca e imprime los primeros 500 numeros primeros
@ Input: --
@ Output: 500 numero primos

@ :(
######## COde Segment  ##################################################

@ Basado en Knuth TAOCP vol. 1 147ff
@ He utilizado las etiquetas y os usos de las variables de Knuth, hasta cierto punto.

@@@@@@@@@@@@@
@ registros @
@@@@@@@@@@@@@

@ r1 apuntar a direcciones de "primos"
@ r3 numero que estamos revisando     ( n e knuth)
@ r4 recuento de primos               ( j en knuth)
@ r5 divisores que estamos revisando
@ r6 indice para los divisores principales
@ r7 contendra recordatorio           ( r en knuth)
@ r8 mantendra el cociente            ( q en knuth)
@ r9 numeros de primos buscados.

.section     .bss
.comm prime, 2000           @reserva espacio para los numeros primos

.section     .data
spc:                        @reserva espacio para los numeros primos con 3 espacios
.ascii " "
len = . - spc
nl:                         @ linea nueva
      .ascii " "

limit:                      @ indicador del ultimo numero primo que necesitaremos

      .long 500

.section .text
.global _start
_start:

p1:                         @ configuraion
ldr r1, =prime              @ el punto r1 es "prime"
mov r0, $2                  @ el primer primo es 2
str r0, [r1]                @ almacenamos este numero en "prime"
ldr r0, =limit
ldr r9, [r0]                @ r2 mantiene el numero de primos que buscaremos
mov r3, $3                  @ inicializa n en 3
mov r4, $1                  @ inicializa j en 1

p2:                         @ aqui llegamos cuando encontramos un numero primo
add r4, r4, $1              @ se incrementa j
str r3,  [r1, #4]!          @ almacena n en "prime" (con writeback)

p3:
cmp r4, r9                  @ revisa si esta hecho
bge p9                      @ si es asi a p9

p4:
add r3, r3, $2              @ añade 2 a n

p5:                         @ empieza a verificar los divisores
ldr r6, =prime              @ copia el puntero a start de "prime"
ldr r5, [r6]                @ carga el primer divisor
mov r7, r3                  @ copia n en r
mov r8, $0                  @ inicializa q

p6:
cmp r7, r5                  @ if r>= divisor
subge r7, r7, r5            @ sustrae divisor desde r
addge r8, r8, $1            @ incrementa q
bge p6                      @ repite
cmp r7, $0                  @ if r ==0 ...
beq p4                      @ n no es primo, asi que prueba el siguiente n

p7:
cmp r8, r5                  @ compare q con el divisor
ble p2                      @ if q <= divisor, n es primo

p8:
mov r7, r3                  @ reinicia r7 a n
mov r8, $0                  @ reinicia q
ldr r5,  [r6, #4]           @ obtiene el siguiente divisor
bol p6                      @ divide otra vez

p9:
mov r0, $1                  @ elige stdout
mov r4, $0                  @ usa r4 como un contador temporal
mov r5, $0                  @ r5 cuenta el total de numeros primos impresos
ldr r6, =prime              @ puntero a "prime"
ldr r3, [r6]                @ carga el primer numero primo

printloop:
bl print_num                @ llamada de funcion
add r4, $1                  @ añade uno al contador temporal
add r5, $1                  @ añade uno al contador
cmp r5, r9                  @ aqui es donde terminamos?
bge exit                    @ si es asi, salida
cmp r4, $9                  @ after 10 numeros primos ...
bgt newline                 @ imprime una nueva linea
ble space                   @ añade espacio



space:                      @ saltamos aqui si
mov r0, $1                  @ vamos a
ldr r1, =spc                @ imprimir espacios
ldr r2, =len
mov r7, $4
svc $0
ldr r3, [r6, #4]            @ carga el siguiente numero primo
bal printloop               @ cuntinua imprimiendo

newline:                    @ saltamos aqui si
mov r0, $1                  @ vamos a
ldr r1, =nl                 @ imprimir una nueva linea
mov r2, $1
mov r7, $4
svc $0
ldr r3, [r6, #4]            @ carga el siguiente numero primo
mov r4, $0                  @ reinicia el contador temporal
bal printloop               @ continua imprimiendo


@@@@@@@@@@@@@@@@@@@@@@
@ print_num function @
@@@@@@@@@@@@@@@@@@@@@@

  ####### data segment ####################################################

print_num:
  stmfd sp!, {r0-r9, lr}    @ push regs a la pila
  mov r4, $0                @ propone contador de division a zero
  mov r5, $1                @ propone contador char a 1

loop:                       @ division de rutina
cmp r3, $9
ble stackpush               @ if r3 <= 9, llama al apilador
sub r3, r3, $10             @ entonces, sustrae 10 desde r3
add r4, r4, $1              @ añade 1 a contador de division
bal loop                    @ repite

stackpush:
add r5, r5, $1              @ incrementa el contador char
orr r0, r3, $0x30           @ logico or - añade 48 a diditos para obtere codigo ascii
stmfd sp!, {r0}             @ empuja dento de la pila
cmp r4, $0                  @ si el contador de division es zero...
beq printchars              @ llama la funcion de impresion
mov r3, r4                  @ entonces, carga contador de division en r3
mov r4, $0                  @reinicia contador de division 
bal loop                    @regresa al tope de loop

printchars:
mov r1, sp                  @ usa el apuntador de la pila para proveer codigo ascii
mov r0, $1                  @ stdout es el archivo descriptor 1
mov r2, $1                  @ longitud de imprimir es 1
mov r7, $4                  @ escribe syscall
svc $0                      @ wake kernel!!!!!
subs r5, r5, $1             @ decrementa el contador string y establece la bandera
ble return                  @ regresa si esta hecho
ldmfd sp!, {0}              @ jala el siguiente char desde la pila
bal prinntchars             @ obtiene el siguiente char
return:
ldmfd sp!, {r0-r9, pc}      @ reinicia registros

exit:                       @ imprime una nueva linea
mov r0, $1
ldr r1, =nl
mov r7, $4
svc $0
mov r7, $1                  @ exit
svc $0

.end




